
<!DOCTYPE html
  PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
   <head>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
   
      <title>16.2.&nbsp;找到路径</title>
      <link rel="stylesheet" href="../diveintopython.css" type="text/css">
      <link rev="made" href="mailto:f8dy@diveintopython.org">
      <meta name="generator" content="DocBook XSL Stylesheets V1.52.2">
      <meta name="keywords" content="Python, Dive Into Python, tutorial, object-oriented, programming, documentation, book, free">
      <meta name="description" content="Python from novice to pro">
      <link rel="home" href="../toc/index.html" title="Dive Into Python">
      <link rel="up" href="index.html" title="第&nbsp;16&nbsp;章&nbsp;函数编程">
      <link rel="previous" href="index.html" title="第&nbsp;16&nbsp;章&nbsp;函数编程">
      <link rel="next" href="filtering_lists.html" title="16.3.&nbsp;重识列表过滤">
   </head>
   <body>
      <table id="Header" width="100%" border="0" cellpadding="0" cellspacing="0" summary="">
         <tr>
            <td id="breadcrumb" colspan="5" align="left" valign="top">导航：<a href="../index.html">起始页</a>&nbsp;&gt;&nbsp;<a href="../toc/index.html">Dive Into Python</a>&nbsp;&gt;&nbsp;<a href="index.html">函数编程</a>&nbsp;&gt;&nbsp;<span class="thispage">找到路径</span></td>
            <td id="navigation" align="right" valign="top">&nbsp;&nbsp;&nbsp;<a href="index.html" title="上一页: “函数编程”">&lt;&lt;</a>&nbsp;&nbsp;&nbsp;<a href="filtering_lists.html" title="下一页: “重识列表过滤”">&gt;&gt;</a></td>
         </tr>
         <tr>
            <td colspan="3" id="logocontainer">
               <h1 id="logo"><a href="../index.html" accesskey="1">深入 Python :Dive Into Python 中文版</a></h1>
               <p id="tagline">Python 从新手到专家 [Dip_5.4b_CPyUG_Release]</p>
            </td>
            <td colspan="3" align="right">
               <form id="search" method="GET" action="http://www.google.com/custom">
                  <p><label for="q" accesskey="4">Find:&nbsp;</label><input type="text" id="q" name="q" size="20" maxlength="255" value=""> <input type="submit" value="搜索"><input type="hidden" name="domains" value="woodpecker.org.cn/diveintopython"><input type="hidden" name="sitesearch" value="www.woodpecker.org.cn/diveintopython"></p>
               </form>
            </td>
         </tr>
      </table>
      <!--#include virtual="/inc/ads" -->
      <div class="section" lang="zh_cn">
         <div class="titlepage">
            <div>
               <div>
                  <h2 class="title"><a name="regression.path"></a>16.2.&nbsp;找到路径
                  </h2>
               </div>
            </div>
            <div></div>
         </div>
         <div class="abstract">
            <p>从命令行运行 <span class="application">Python</span> 代码时，知道所运行代码在磁盘上的存储位置有时候是有必要的。
            </p>
         </div>
         <p>这是一个不那么容易想起，但一想起就很容易解决的小麻烦。答案是 <tt class="literal">sys.argv</tt>。正如你在 <a href="../xml_processing/index.html" title="第&nbsp;9&nbsp;章&nbsp;XML 处理">第&nbsp;9&nbsp;章 <i>XML 处理</i></a> 中看到的，它包含了很多命令行参数。它也同样记录了运行脚本的名字，和你调用它时使用的命令一摸一样。这些信息足以令我们确定文件的位置。
         </p>
         <div class="example"><a name="d0e35531"></a><h3 class="title">例&nbsp;16.3.&nbsp;<tt class="filename">fullpath.py</tt></h3>
            <p>如果您还没有下载本书附带的样例程序, 可以 <a href="http://www.woodpecker.org.cn/diveintopython/download/diveintopython-exampleszh-cn-5.4b.zip" title="Download example scripts">下载本程序和其他样例程序</a>。
            </p><pre class="programlisting"><span class='pykeyword'>
import</span> sys, os

<span class='pykeyword'>print</span> <span class='pystring'>'sys.argv[0] ='</span>, sys.argv[0]             <a name="regression.path.1.1"></a><img src="../images/callouts/1.png" alt="1" border="0" width="12" height="12">
pathname = os.path.dirname(sys.argv[0])        <a name="regression.path.1.2"></a><img src="../images/callouts/2.png" alt="2" border="0" width="12" height="12"><span class='pykeyword'>
print</span> <span class='pystring'>'path ='</span>, pathname
<span class='pykeyword'>print</span> <span class='pystring'>'full path ='</span>, os.path.abspath(pathname) <a name="regression.path.1.3"></a><img src="../images/callouts/3.png" alt="3" border="0" width="12" height="12"></pre><div class="calloutlist">
               <table border="0" summary="Callout list">
                  <tr>
                     <td width="12" valign="top" align="left"><a href="#regression.path.1.1"><img src="../images/callouts/1.png" alt="1" border="0" width="12" height="12"></a> 
                     </td>
                     <td valign="top" align="left">无论如何运行一段脚本，<tt class="literal">sys.argv[0]</tt> 总是包含脚本的名字，和调用时使用的命令一摸一样。你很快会发现，它不一定包含任何路径信息。
                     </td>
                  </tr>
                  <tr>
                     <td width="12" valign="top" align="left"><a href="#regression.path.1.2"><img src="../images/callouts/2.png" alt="2" border="0" width="12" height="12"></a> 
                     </td>
                     <td valign="top" align="left"><tt class="function">os.path.dirname</tt> 接受作为字符串传来的文件名并返回路径部分。如果给定的文件名不包含任何路径信息，<tt class="function">os.path.dirname</tt>  返回空字符串。
                     </td>
                  </tr>
                  <tr>
                     <td width="12" valign="top" align="left"><a href="#regression.path.1.3"><img src="../images/callouts/3.png" alt="3" border="0" width="12" height="12"></a> 
                     </td>
                     <td valign="top" align="left"><tt class="function">os.path.abspath</tt> 是这里的关键。它接受的路径名可以是部分的甚至是完全空白，但总能返回完整有效的路径名。
                     </td>
                  </tr>
               </table>
            </div>
         </div>
         <p>进一步地解释 <tt class="function">os.path.abspath</tt> 是有必要的。它非常灵活，可以接受任何类型的路径名。
         </p>
         <div class="example"><a name="d0e35572"></a><h3 class="title">例&nbsp;16.4.&nbsp;<tt class="function">os.path.abspath</tt> 的进一步解释
            </h3><pre class="screen">
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput"><span class='pykeyword'>import</span> os</span>
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">os.getcwd()</span>                        <a name="regression.path.2.1"></a><img src="../images/callouts/1.png" alt="1" border="0" width="12" height="12">
<span class="computeroutput">/home/you</span>
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">os.path.abspath(<span class='pystring'>''</span>)</span>                <a name="regression.path.2.2"></a><img src="../images/callouts/2.png" alt="2" border="0" width="12" height="12">
<span class="computeroutput">/home/you</span>
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">os.path.abspath(<span class='pystring'>'.ssh'</span>)</span>            <a name="regression.path.2.3"></a><img src="../images/callouts/3.png" alt="3" border="0" width="12" height="12">
<span class="computeroutput">/home/you/.ssh</span>
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">os.path.abspath(<span class='pystring'>'/home/you/.ssh'</span>)</span> <a name="regression.path.2.4"></a><img src="../images/callouts/4.png" alt="4" border="0" width="12" height="12">
<span class="computeroutput">/home/you/.ssh</span>
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">os.path.abspath(<span class='pystring'>'.ssh/../foo/'</span>)</span>    <a name="regression.path.2.5"></a><img src="../images/callouts/5.png" alt="5" border="0" width="12" height="12">
<span class="computeroutput">/home/you/foo</span></pre><div class="calloutlist">
               <table border="0" summary="Callout list">
                  <tr>
                     <td width="12" valign="top" align="left"><a href="#regression.path.2.1"><img src="../images/callouts/1.png" alt="1" border="0" width="12" height="12"></a> 
                     </td>
                     <td valign="top" align="left"><tt class="function">os.getcwd()</tt> 返回当前的工作路径。
                     </td>
                  </tr>
                  <tr>
                     <td width="12" valign="top" align="left"><a href="#regression.path.2.2"><img src="../images/callouts/2.png" alt="2" border="0" width="12" height="12"></a> 
                     </td>
                     <td valign="top" align="left">用空字符串调用 <tt class="function">os.path.abspath</tt> 将返回当前的工作路径，与 <tt class="function">os.getcwd()</tt>的效果相同。
                     </td>
                  </tr>
                  <tr>
                     <td width="12" valign="top" align="left"><a href="#regression.path.2.3"><img src="../images/callouts/3.png" alt="3" border="0" width="12" height="12"></a> 
                     </td>
                     <td valign="top" align="left">以不完整的路径名调用 <tt class="function">os.path.abspath</tt> 可以构建一个基于当前工作路径且完整有效的路径名。
                     </td>
                  </tr>
                  <tr>
                     <td width="12" valign="top" align="left"><a href="#regression.path.2.4"><img src="../images/callouts/4.png" alt="4" border="0" width="12" height="12"></a> 
                     </td>
                     <td valign="top" align="left">以完整的路径名调用 <tt class="function">os.path.abspath</tt> 则简单地将其直接返回。
                     </td>
                  </tr>
                  <tr>
                     <td width="12" valign="top" align="left"><a href="#regression.path.2.5"><img src="../images/callouts/5.png" alt="5" border="0" width="12" height="12"></a> 
                     </td>
                     <td valign="top" align="left"><tt class="function">os.path.abspath</tt> 还<span class="emphasis"><em>格式化</em></span> 返回的路径名。注意这个例子在我根本没有‘foo’目录时同样奏效。<tt class="function">os.path.abspath</tt> 从不检查你的磁盘，而仅仅是字符串操作。
                     </td>
                  </tr>
               </table>
            </div>
         </div><a name="os.path.abspath.exist.note"></a><table class="note" border="0" summary="">
            <tr>
               <td rowspan="2" align="center" valign="top" width="1%"><img src="../images/note.png" alt="注意" title="" width="24" height="24"></td>
            </tr>
            <tr>
               <td colspan="2" align="left" valign="top" width="99%">传递给 <tt class="function">os.path.abspath</tt> 的路径名和文件名可以不存在。
               </td>
            </tr>
         </table><a name="os.path.normpath.note"></a><table class="note" border="0" summary="">
            <tr>
               <td rowspan="2" align="center" valign="top" width="1%"><img src="../images/note.png" alt="注意" title="" width="24" height="24"></td>
            </tr>
            <tr>
               <td colspan="2" align="left" valign="top" width="99%"><tt class="function">os.path.abspath</tt> 不仅构建完整路径名，还能格式化路径名。这意味着如果你正工作于 <tt class="filename">/usr/</tt> 目录，<tt class="literal">os.path.abspath('bin/../local/bin')</tt> 将会返回 <tt class="filename">/usr/local/bin</tt>。它把路径名格式化为尽可能简单的形式。如果你只是希望简单地返回这样的格式化路径名而不需要完整路径名，可以使用 <tt class="function">os.path.normpath</tt>。
               </td>
            </tr>
         </table>
         <div class="example"><a name="d0e35700"></a><h3 class="title">例&nbsp;16.5.&nbsp;<tt class="filename">fullpath.py</tt> 的样例输出
            </h3><pre class="screen">
<tt class="prompt">[you@localhost py]$ </tt><span class="userinput">python /home/you/diveintopython/common/py/fullpath.py</span> <a name="regression.path.3.1"></a><img src="../images/callouts/1.png" alt="1" border="0" width="12" height="12">
<span class="computeroutput">sys.argv[0] = /home/you/diveintopython/common/py/fullpath.py
path = /home/you/diveintopython/common/py
full path = /home/you/diveintopython/common/py</span>
<tt class="prompt">[you@localhost diveintopython]$ </tt><span class="userinput">python common/py/fullpath.py</span>               <a name="regression.path.3.2"></a><img src="../images/callouts/2.png" alt="2" border="0" width="12" height="12">
<span class="computeroutput">sys.argv[0] = common/py/fullpath.py
path = common/py
full path = /home/you/diveintopython/common/py</span>
<tt class="prompt">[you@localhost diveintopython]$ </tt><span class="userinput">cd common/py</span>
<tt class="prompt">[you@localhost py]$ </tt><span class="userinput">python fullpath.py</span>                                     <a name="regression.path.3.3"></a><img src="../images/callouts/3.png" alt="3" border="0" width="12" height="12">
<span class="computeroutput">sys.argv[0] = fullpath.py
path = 
full path = /home/you/diveintopython/common/py</span></pre><div class="calloutlist">
               <table border="0" summary="Callout list">
                  <tr>
                     <td width="12" valign="top" align="left"><a href="#regression.path.3.1"><img src="../images/callouts/1.png" alt="1" border="0" width="12" height="12"></a> 
                     </td>
                     <td valign="top" align="left">在第一种情况下，<tt class="literal">sys.argv[0]</tt> 包含代码的完整路径。你可以通过 <tt class="function">os.path.dirname</tt> 函数将文件名从其中剥离出来并返回完整的路径，<tt class="function">os.path.abspath</tt> 则是简单地把你传递给它的值返回。
                     </td>
                  </tr>
                  <tr>
                     <td width="12" valign="top" align="left"><a href="#regression.path.3.2"><img src="../images/callouts/2.png" alt="2" border="0" width="12" height="12"></a> 
                     </td>
                     <td valign="top" align="left">如果脚本是以不完整路名被运行的，<tt class="literal">sys.argv[0]</tt> 还是会包含命令行中出现的一切。<tt class="function">os.path.dirname</tt> 将会给你一个 (相对于当前工作路径的) 不完整的路径名，<tt class="function">os.path.abspath</tt> 将会以不完整路径名为基础构建一个完整的路径名。
                     </td>
                  </tr>
                  <tr>
                     <td width="12" valign="top" align="left"><a href="#regression.path.3.3"><img src="../images/callouts/3.png" alt="3" border="0" width="12" height="12"></a> 
                     </td>
                     <td valign="top" align="left">如果没有给定任何路径，而是从当前目录运行脚本，<tt class="function">os.path.dirname</tt> 将简单地返回一个空字符串。由于是从当前目录运行脚本，<tt class="function">os.path.abspath</tt> 将针对给定的空字符串给出你所希望获知的当前目录。
                     </td>
                  </tr>
               </table>
            </div>
         </div><a name="os.path.abspath.crossplatform.note"></a><table class="note" border="0" summary="">
            <tr>
               <td rowspan="2" align="center" valign="top" width="1%"><img src="../images/note.png" alt="注意" title="" width="24" height="24"></td>
            </tr>
            <tr>
               <td colspan="2" align="left" valign="top" width="99%">就像 <tt class="filename">os</tt> 和 <tt class="filename">os.path</tt> 模块的其他函数，<tt class="function">os.path.abspath</tt> 是跨平台的。如果你是在 Windows (使用反斜杠作为路径符号) 或 <span class="abbrev">Mac</span> <span class="acronym">OS</span> (使用冒号) 上运行，它们同样工作，只是将获得与我稍有不同的结果。<tt class="filename">os</tt> 的所有函数都是这样的。
               </td>
            </tr>
         </table>
         <p><b>补充.&nbsp;</b>一位读者对这个结果并不满意，他希望能够从当前路径运行所有单元测试，而不是从 <tt class="filename">regression.py</tt> 所在目录运行。他建议以下面的代码加以取代：
         </p>
         <div class="example"><a name="regression.path.cwd.example"></a><h3 class="title">例&nbsp;16.6.&nbsp;在当前目录运行脚本</h3><pre class="programlisting"><span class='pykeyword'>import</span> sys, os, re, unittest

<span class='pykeyword'>def</span><span class='pyclass'> regressionTest</span>():
    path = os.getcwd()       <a name="regression.path.4.1"></a><img src="../images/callouts/1.png" alt="1" border="0" width="12" height="12">
    sys.path.append(path)    <a name="regression.path.4.2"></a><img src="../images/callouts/2.png" alt="2" border="0" width="12" height="12">
    files = os.listdir(path) <a name="regression.path.4.3"></a><img src="../images/callouts/3.png" alt="3" border="0" width="12" height="12">
</pre><div class="calloutlist">
               <table border="0" summary="Callout list">
                  <tr>
                     <td width="12" valign="top" align="left"><a href="#regression.path.4.1"><img src="../images/callouts/1.png" alt="1" border="0" width="12" height="12"></a> 
                     </td>
                     <td valign="top" align="left">不是将 <tt class="varname">path</tt> 设置为运行代码所在的路径，而是将它设置为当前目录。可以是你在运行脚本之前所在的任何路径，而不需要是运行脚本所在的路径。(多次体味这句话，直到你真正理解了它。)
                     </td>
                  </tr>
                  <tr>
                     <td width="12" valign="top" align="left"><a href="#regression.path.4.2"><img src="../images/callouts/2.png" alt="2" border="0" width="12" height="12"></a> 
                     </td>
                     <td valign="top" align="left">将这个目录添加到  <span class="application">Python</span> 库搜索路径中，你稍后动态导入单元测试模块时，<span class="application">Python</span> 就能找到它们了。如果 <tt class="varname">path</tt> 就是正在运行代码的存储目录，你就不需要这样做了，因为 <span class="application">Python</span> 总会查找这个目录。
                     </td>
                  </tr>
                  <tr>
                     <td width="12" valign="top" align="left"><a href="#regression.path.4.3"><img src="../images/callouts/3.png" alt="3" border="0" width="12" height="12"></a> 
                     </td>
                     <td valign="top" align="left">函数的其他部分不变。</td>
                  </tr>
               </table>
            </div>
            <p>这个技术允许你在多个项目中重用 <tt class="filename">regression.py</tt> 代码。只需要将这个代码放在一个普通目录中，在运行项目前将路径更改为项目的目录。项目中所有的单元测试被找到并运行，而不仅仅局限于 <tt class="filename">regression.py</tt> 所在目录的单元测试。
            </p>
         </div>
      </div>
      <table class="Footer" width="100%" border="0" cellpadding="0" cellspacing="0" summary="">
         <tr>
            <td width="35%" align="left"><br><a class="NavigationArrow" href="index.html">&lt;&lt;&nbsp;函数编程</a></td>
            <td width="30%" align="center"><br>&nbsp;<span class="divider">|</span>&nbsp;<a href="index.html#regression.divein" title="16.1.&nbsp;概览">1</a> <span class="divider">|</span> <span class="thispage">2</span> <span class="divider">|</span> <a href="filtering_lists.html" title="16.3.&nbsp;重识列表过滤">3</a> <span class="divider">|</span> <a href="mapping_lists.html" title="16.4.&nbsp;重识列表映射">4</a> <span class="divider">|</span> <a href="data_centric.html" title="16.5.&nbsp;数据中心思想编程">5</a> <span class="divider">|</span> <a href="dynamic_import.html" title="16.6.&nbsp;动态导入模块">6</a> <span class="divider">|</span> <a href="all_together.html" title="16.7.&nbsp;全部放在一起">7</a> <span class="divider">|</span> <a href="summary.html" title="16.8.&nbsp;小结">8</a>&nbsp;<span class="divider">|</span>&nbsp;
            </td>
            <td width="35%" align="right"><br><a class="NavigationArrow" href="filtering_lists.html">重识列表过滤&nbsp;&gt;&gt;</a></td>
         </tr>
         <tr>
            <td colspan="3"><br></td>
         </tr>
      </table>
      <div class="Footer">
         <p class="copyright">Copyright © 2000, 2001, 2002, 2003, 2004 <a href="mailto:mark@diveintopython.org">Mark Pilgrim</a></p>
         <p class="copyright">Copyright © 2001, 2002, 2003, 2004, 2005, 2006, 2007 <a href="mailto:python-cn@googlegroups.com">CPyUG (邮件列表)</a></p>
      </div>
   </body>
</html>